1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  package com.macvu.tiles.taglib;
63  
64  import com.macvu.tiles.CacheComponentDefinition;
65  import com.macvu.tiles.CacheInformation;
66  import com.macvu.tiles.cache.CacheObjectWrapper;
67  import com.macvu.tiles.capture.CacheHttpServletResponse;
68  import com.macvu.tiles.capture.CacheablesCaptureWrapper;
69  import org.apache.commons.logging.Log;
70  import org.apache.commons.logging.LogFactory;
71  import org.apache.struts.taglib.tiles.ComponentConstants;
72  import org.apache.struts.taglib.tiles.InsertTag;
73  import org.apache.struts.tiles.ComponentContext;
74  import org.apache.struts.tiles.ComponentDefinition;
75  import org.apache.struts.tiles.Controller;
76  import org.apache.struts.tiles.TilesUtil;
77  import org.apache.struts.util.ResponseUtils;
78  
79  import javax.servlet.ServletContext;
80  import javax.servlet.ServletException;
81  import javax.servlet.http.HttpServletRequest;
82  import javax.servlet.http.HttpServletResponse;
83  import javax.servlet.jsp.JspException;
84  import javax.servlet.jsp.PageContext;
85  import java.io.IOException;
86  import java.io.PrintWriter;
87  
88  public class CacheInsertTag extends InsertTag {
89  
90      protected static Log log = LogFactory.getLog(CacheInsertTag.class);
91  
92      /***
93       * Get current component context.
94       */
95      private ComponentContext getCurrentContext() {
96          if (cachedCurrentContext == null) {
97              cachedCurrentContext =
98                      (ComponentContext) pageContext.getAttribute(ComponentConstants.COMPONENT_CONTEXT,
99                              PageContext.REQUEST_SCOPE);
100         }
101         return cachedCurrentContext;
102     }
103 
104     /***
105      * End of Process tag attribute "definition".
106      * Overload definition with tag attributes "template" and "role".
107      * Then, create appropriate tag handler.
108      *
109      * @param definition Definition to process.
110      * @return Appropriate TagHandler.
111      * @throws JspException InstantiationException Can't create requested controller
112      */
113     protected TagHandler processDefinition(ComponentDefinition definition)
114             throws JspException {
115         
116         String role = this.role;
117         String page = this.page;
118         Controller controller = null;
119 
120         if (log.isDebugEnabled()) {
121             log.debug("Process Definition: " + definition.getName());
122         }
123         try {
124             controller = definition.getOrCreateController();
125 
126             
127             if (role == null) {
128                 role = definition.getRole();
129             }
130             if (page == null) {
131                 page = definition.getTemplate();
132             }
133             if (controllerName != null) {
134                 controller =
135                         ComponentDefinition.createController(controllerName,
136                                 controllerType);
137             }
138 
139             if (definition instanceof CacheComponentDefinition) {
140                 
141                 return new CacheInsertHandler((CacheComponentDefinition) definition,
142                         page,
143                         role,
144                         controller);
145             } else {
146                 
147                 return new InsertHandler(definition.getAttributes(),
148                         page,
149                         role,
150                         controller);
151             }
152         } catch (InstantiationException ex) {
153             throw new JspException(ex.getMessage());
154         }
155     }
156 
157     /***
158      * Do an include of specified page.
159      * This method is used internally to do all includes from this class. It delegates
160      * the include call to the TilesUtil.doInclude().
161      *
162      * @param page The page that will be included
163      * @throws ServletException - Thrown by call to pageContext.include()
164      * @throws IOException      - Thrown by call to pageContext.include()
165      */
166     protected void doInclude(String page, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) throws ServletException, IOException {
167         
168 
169 
170 
171 
172 
173         TilesUtil.doInclude(page, request, response, servletContext);
174     }
175 
176     protected class CacheInsertHandler implements TagHandler {
177         protected CacheComponentDefinition definition;
178         protected String page;
179         protected ComponentContext currentContext;
180         protected ComponentContext subCompContext;
181         protected String role;
182         protected Controller controller;
183 
184         /***
185          * Constructor.
186          * Create insert handler using Component definition.
187          */
188         public CacheInsertHandler(CacheComponentDefinition definition,
189                                   String page,
190                                   String role,
191                                   Controller controller) {
192             this.definition = definition;
193             this.page = page;
194             this.role = role;
195             this.controller = controller;
196             subCompContext = new ComponentContext(definition.getAttributes());
197         }
198 
199         /***
200          * Create a new empty context.
201          */
202         public int doStartTag() throws JspException {
203             
204             if (role != null
205                     && !((HttpServletRequest) pageContext.getRequest()).isUserInRole(role)) {
206                 return SKIP_BODY;
207             }
208 
209             
210             this.currentContext = getCurrentContext();
211             return EVAL_BODY_INCLUDE;
212         }
213 
214         /***
215          * Add attribute to sub context.
216          * Do nothing.
217          */
218         public void putAttribute(String name, Object value) {
219             subCompContext.putAttribute(name, value);
220         }
221 
222         /***
223          * Include requested page.
224          */
225         public int doEndTag() throws JspException {
226             
227             if (role != null
228                     && !((HttpServletRequest) pageContext.getRequest()).isUserInRole(role)) {
229                 return EVAL_PAGE;
230             }
231 
232             try {
233                 if (log.isDebugEnabled()) {
234                     log.debug("insert page='" + page + "'.");
235                 }
236 
237                 HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
238                 HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
239                 ServletContext servletContext = pageContext.getServletContext();
240 
241                 
242                 CacheablesCaptureWrapper cacheables = new CacheablesCaptureWrapper(servletContext);
243                 if (cacheables.isEnableCapture()) {
244                     cacheables.captureCacheablesForTile((CacheComponentDefinition) definition, pageContext);
245                 }
246 
247                 CacheObjectWrapper cacheController = new CacheObjectWrapper();
248                 CacheInformation info = ((CacheComponentDefinition) definition).getCacheInformation();
249                 cacheController.initiateCacheInformation(pageContext.getServletContext(), info);
250                 if (cacheController.isCacheEnabled()) {
251                     String key = cacheController.getCacheKey((HttpServletRequest) pageContext.getRequest());
252                     if (log.isDebugEnabled()) {
253                         log.debug("Cache is enable.  Looking for key: " + key);
254                     }
255                     String cache = (String) cacheController.getCache(key);
256                     if (cache == null) {
257                         CacheHttpServletResponse cacheResponse = new CacheHttpServletResponse(response);
258                         performTileSection(request, cacheResponse, servletContext);
259                         cacheController.putCache(key, cacheResponse.getCache());
260                     } else {
261                         ResponseUtils.write(pageContext, cache);
262                     }
263                 } else {
264                     performTileSection(request, response, servletContext);
265                 }
266             } catch (IOException ex) {
267                 processException(ex,
268                         "Can't insert page '" + page + "' : " + ex.getMessage());
269 
270             } catch (IllegalArgumentException ex) { 
271                 
272                 if (!(page == null && isErrorIgnored)) {
273                     
274                     processException(ex,
275                             "Tag 'insert' can't insert page '"
276                             + page
277                             + "'. Check if it exists.\n"
278                             + ex.getMessage());
279                 }
280 
281             } catch (ServletException ex) {
282                 Throwable realEx = ex;
283                 if (ex.getRootCause() != null) {
284                     realEx = ex.getRootCause();
285                 }
286                 processException(realEx,
287                         "[ServletException in:"
288                         + page
289                         + "] "
290                         + realEx.getMessage()
291                         + "'");
292 
293             } catch (Exception ex) {
294                 processException(ex,
295                         "[Exception in:" + page + "] " + ex.getMessage());
296 
297             } finally {
298                 
299                 
300                 if (currentContext != null) {
301                     pageContext.setAttribute(ComponentConstants.COMPONENT_CONTEXT,
302                             currentContext,
303                             PageContext.REQUEST_SCOPE);
304                 }
305             }
306             return EVAL_PAGE;
307         }
308 
309         private void performTileSection(HttpServletRequest request, HttpServletResponse response, ServletContext context) throws ServletException, IOException {
310             if (log.isDebugEnabled()) {
311                 log.debug("performTileSection: Enter");
312             }
313             
314             pageContext.setAttribute(ComponentConstants.COMPONENT_CONTEXT,
315                     subCompContext,
316                     PageContext.REQUEST_SCOPE);
317 
318             
319             if (controller != null) {
320                 controller.perform(subCompContext,
321                         request,
322                         response,
323                         context);
324             }
325 
326             
327             if (flush) {
328                 pageContext.getOut().flush();
329             }
330 
331             if (log.isDebugEnabled()) {
332                 log.debug("Do Include Page: " + page);
333             }
334             doInclude(page,
335                     request,
336                     response,
337                     context);
338         }
339 
340         /***
341          * Process an exception.
342          * Depending of debug attribute, print full exception trace or only
343          * its message in output page.
344          *
345          * @param ex  Exception
346          * @param msg An additional message to show in console and to propagate if we can't output exception.
347          */
348         protected void processException(Throwable ex, String msg)
349                 throws JspException {
350             try {
351                 if (msg == null) {
352                     msg = ex.getMessage();
353                 }
354                 if (log.isDebugEnabled()) { 
355                     log.debug(msg, ex);
356                     pageContext.getOut().println(msg);
357                     ex.printStackTrace(new PrintWriter(pageContext.getOut(), true));
358                 } else { 
359                     pageContext.getOut().println(msg);
360                 }
361             } catch (IOException ioex) { 
362                 pageContext.setAttribute(ComponentConstants.EXCEPTION_KEY,
363                         ex,
364                         PageContext.REQUEST_SCOPE);
365                 throw new JspException(msg);
366             }
367         }
368     }
369 
370 }